﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace AdbRegisterUtils
{
    public static class CmdUtils
    {
        private const int DefaultDelayMs = 100;
        private const int DefaultTimeoutMs = 30000;
        private const int QuickCommandTimeoutMs = 10000;
        static  ProcessStartInfo startInfo;
        /// <summary>
        /// 创建进程启动信息
        /// </summary>
        private static ProcessStartInfo CreateProcessStartInfo(string workingDirectory, bool showWindow)
        {
            Console.WriteLine($"[CmdUtils] 创建进程启动信息 - 工作目录: '{workingDirectory}', 显示窗口: {showWindow}");

             startInfo = new ProcessStartInfo
            {
                FileName = "cmd.exe",
                RedirectStandardInput = true,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                UseShellExecute = false,
                CreateNoWindow = !showWindow,
                WorkingDirectory = workingDirectory ?? string.Empty,
                StandardOutputEncoding = Encoding.UTF8,
                StandardErrorEncoding = Encoding.UTF8
            };

            return startInfo;
        }

        /// <summary>
        /// 检查ADB是否存在于工作目录
        /// </summary>
        private static bool CheckAdbExists(string workingDirectory)
        {
            if (string.IsNullOrEmpty(workingDirectory))
                return false;

            try
            {
                string adbPath = Path.Combine(workingDirectory, "adb.exe");
                bool exists = File.Exists(adbPath);
                Console.WriteLine($"[CmdUtils] 检查ADB存在: {adbPath} -> {exists}");
                return exists;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[CmdUtils] 检查ADB存在时出错: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 执行单个命令
        /// </summary>
        public static string ExecuteCommand(string command, string workingDirectory, bool showWindow = false, int delayMs = DefaultDelayMs)
        {
            Console.WriteLine($"[CmdUtils] 执行命令: '{command}'");
            return ExecuteCommands(new[] { command }, workingDirectory, showWindow, delayMs);
        }

        /// <summary>
        /// 执行多个命令
        /// </summary>
        public static string ExecuteCommands(string[] commands, string workingDirectory, bool showWindow = false, int delayMs = DefaultDelayMs)
        {
            Console.WriteLine($"[CmdUtils] 执行命令组 - 命令数量: {commands?.Length}, 工作目录: '{workingDirectory}', 显示窗口: {showWindow}");

            if (commands == null || commands.Length == 0)
            {
                Console.WriteLine($"[CmdUtils] 警告: 命令列表为空");
                return string.Empty;
            }

            var result = new StringBuilder();
            var startInfo = CreateProcessStartInfo(workingDirectory, showWindow);

            using (var process = new Process())
            {
                process.StartInfo = startInfo;

                // 输出数据接收事件
                process.OutputDataReceived += (s, e) =>
                {
                    if (!string.IsNullOrEmpty(e.Data))
                    {
                        Console.WriteLine($"[CMD-OUT] {e.Data}");
                        lock (result)
                        {
                            result.AppendLine(e.Data);
                        }
                    }
                };

                // 错误数据接收事件
                process.ErrorDataReceived += (s, e) =>
                {
                    if (!string.IsNullOrEmpty(e.Data))
                    {
                        Console.WriteLine($"[CMD-ERR] {e.Data}");
                        lock (result)
                        {
                            result.AppendLine($"[ERROR] {e.Data}");
                        }
                    }
                };

                Console.WriteLine($"[CmdUtils] 启动进程...");
                process.Start();
                Console.WriteLine($"[CmdUtils] 进程已启动 (ID: {process.Id})");

                // 开始异步读取
                process.BeginOutputReadLine();
                process.BeginErrorReadLine();

                try
                {
                    // 依次执行所有命令
                    for (int i = 0; i < commands.Length; i++)
                    {
                        var command = commands[i];
                        if (!string.IsNullOrEmpty(command))
                        {
                            Console.WriteLine($"[CmdUtils] 执行命令 [{i + 1}/{commands.Length}]: {command}");
                            process.StandardInput.WriteLine(command);

                            if (delayMs > 0)
                            {
                                Thread.Sleep(delayMs);
                            }
                        }
                    }

                    Console.WriteLine($"[CmdUtils] 所有命令执行完成，发送退出指令");
                    process.StandardInput.WriteLine("exit");

                    Console.WriteLine($"[CmdUtils] 等待进程退出 (超时: {DefaultTimeoutMs}ms)...");
                    if (process.WaitForExit(DefaultTimeoutMs))
                    {
                        Console.WriteLine($"[CmdUtils] 进程正常退出");
                    }
                    else
                    {
                        Console.WriteLine($"[CmdUtils] 警告: 进程等待超时，强制终止");
                    }

                    // 等待所有异步输出完成
                    Thread.Sleep(200);
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"[CmdUtils] 执行命令时发生异常: {ex.Message}");
                    throw;
                }
                finally
                {
                    // 确保进程被关闭
                    if (!process.HasExited)
                    {
                        Console.WriteLine($"[CmdUtils] 强制终止进程...");
                        process.Kill();
                        Console.WriteLine($"[CmdUtils] 进程已终止");
                    }
                    else
                    {
                        Console.WriteLine($"[CmdUtils] 进程退出代码: {process.ExitCode}");
                    }
                }
            }

            string finalResult = result.ToString();
            Console.WriteLine($"[CmdUtils] 命令执行完成，结果长度: {finalResult.Length} 字符");

            return finalResult;
        }

        /// <summary>
        /// 执行快速ADB命令
        /// </summary>
        public static string ExecuteQuickAdbCommand(string command, string workingDirectory, bool showWindow = false)
        {
            Console.WriteLine($"[CmdUtils] 执行快速ADB命令: '{command}'");

            // 总是使用cmd.exe包装执行ADB命令
            return ExecuteCommand(command, workingDirectory, showWindow);
        }

        /// <summary>
        /// 直接执行ADB命令（修复版本）
        /// </summary>
        public static string ExecuteAdbDirect(string adbCommand, string workingDirectory, bool showWindow = false)
        {
            Console.WriteLine($"[CmdUtils] 直接执行ADB命令: '{adbCommand}'");

            // 检查ADB是否存在
            if (!CheckAdbExists(workingDirectory))
            {
                Console.WriteLine($"[CmdUtils] 警告: ADB未在工作目录中找到，使用cmd.exe包装执行");
                // 如果ADB不存在，回退到cmd.exe包装执行
                return ExecuteCommand(adbCommand, workingDirectory, showWindow);
            }

            var result = new StringBuilder();

            var startInfo = new ProcessStartInfo
            {
                FileName = "adb.exe", // 直接使用adb
                Arguments = adbCommand.Replace("adb ", ""), // 移除前面的adb
                WorkingDirectory = workingDirectory ?? string.Empty,
                UseShellExecute = false,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                CreateNoWindow = !showWindow,
                StandardOutputEncoding = Encoding.UTF8,
                StandardErrorEncoding = Encoding.UTF8
            };

            using (var process = new Process())
            {
                process.StartInfo = startInfo;

                process.OutputDataReceived += (s, e) =>
                {
                    if (!string.IsNullOrEmpty(e.Data))
                    {
                        Console.WriteLine($"[ADB-DIRECT-OUT] {e.Data}");
                        result.AppendLine(e.Data);
                    }
                };

                process.ErrorDataReceived += (s, e) =>
                {
                    if (!string.IsNullOrEmpty(e.Data))
                    {
                        Console.WriteLine($"[ADB-DIRECT-ERR] {e.Data}");
                        result.AppendLine($"[ERROR] {e.Data}");
                    }
                };

                Console.WriteLine($"[CmdUtils] 启动直接ADB进程...");
                try
                {
                    process.Start();
                    Console.WriteLine($"[CmdUtils] 直接ADB进程已启动 (ID: {process.Id})");

                    process.BeginOutputReadLine();
                    process.BeginErrorReadLine();

                    // 设置较短的超时时间
                    if (process.WaitForExit(5000))
                    {
                        Console.WriteLine($"[CmdUtils] 直接ADB进程退出，代码: {process.ExitCode}");
                    }
                    else
                    {
                        Console.WriteLine($"[CmdUtils] 直接ADB进程超时，但命令可能已发送");
                        process.Kill();
                    }

                    Thread.Sleep(300);
                }
                catch (System.ComponentModel.Win32Exception ex)
                {
                    Console.WriteLine($"[CmdUtils] 直接执行ADB失败: {ex.Message}，回退到cmd.exe包装");
                    // 如果直接执行失败，回退到cmd.exe包装执行
                    return ExecuteCommand(adbCommand, workingDirectory, showWindow);
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"[CmdUtils] 直接ADB命令异常: {ex.Message}");
                    throw;
                }
            }

            return result.ToString();
        }

        /// <summary>
        /// 专门用于寄存器读写的ADB命令
        /// </summary>
        public static string ExecuteRegisterCommand(string command, string workingDirectory, bool showWindow = false)
        {
            Console.WriteLine($"[CmdUtils] 执行寄存器命令: '{command}'");

            // 对于寄存器操作，总是使用cmd.exe包装执行，确保兼容性
            return ExecuteCommand(command, workingDirectory, showWindow);
        }

        /// <summary>
        /// 检查ADB是否可用
        /// </summary>
        public static bool CheckAdbAvailable(string workingDirectory)
        {
            try
            {
                Console.WriteLine($"[CmdUtils] 检查ADB是否可用...");
                string result = ExecuteCommand("adb devices", workingDirectory);
                bool available = result.Contains("List of devices attached");
                Console.WriteLine($"[CmdUtils] ADB可用性: {available}");
                return available;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[CmdUtils] 检查ADB可用性时出错: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 执行命令并实时输出（用于长时间运行的进程）
        /// </summary>
        public static void ExecuteCommandWithRealTimeOutput(string command, string workingDirectory, bool showWindow = false)
        {
            Console.WriteLine($"[CmdUtils] 开始执行实时输出命令: '{command}'");

            var startInfo = new ProcessStartInfo
            {
                FileName = "cmd.exe",
                Arguments = $"/c {command}",
                WorkingDirectory = workingDirectory ?? string.Empty,
                UseShellExecute = showWindow,
                CreateNoWindow = !showWindow,
                RedirectStandardOutput = !showWindow,
                RedirectStandardError = !showWindow,
                StandardOutputEncoding = Encoding.UTF8,
                StandardErrorEncoding = Encoding.UTF8
            };

            if (showWindow)
            {
                Console.WriteLine($"[CmdUtils] 显示模式: 启动可见的命令窗口");
                Process.Start(startInfo);
                return;
            }

            using (var process = new Process())
            {
                process.StartInfo = startInfo;

                process.OutputDataReceived += (s, e) =>
                {
                    if (!string.IsNullOrEmpty(e.Data))
                    {
                        Console.WriteLine($"[CMD-OUTPUT] {e.Data}");
                    }
                };

                process.ErrorDataReceived += (s, e) =>
                {
                    if (!string.IsNullOrEmpty(e.Data))
                    {
                        Console.WriteLine($"[CMD-ERROR] {e.Data}");
                    }
                };

                Console.WriteLine($"[CmdUtils] 启动实时命令进程...");
                process.Start();

                process.BeginOutputReadLine();
                process.BeginErrorReadLine();

                Console.WriteLine($"[CmdUtils] 实时命令进程已启动 (ID: {process.Id})");

                // 对于实时命令，我们等待用户中断或进程结束
                try
                {
                    process.WaitForExit();
                    Console.WriteLine($"[CmdUtils] 实时命令进程已退出，代码: {process.ExitCode}");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"[CmdUtils] 等待进程退出时发生异常: {ex.Message}");
                }
            }
        }

        /// <summary>
        /// 简单执行命令（同步方式，适合快速命令）
        /// </summary>
        public static string ExecuteCommandSimple(string command, string workingDirectory, bool showWindow = false)
        {
            Console.WriteLine($"[CmdUtils] 简单执行命令: '{command}'");

            var startInfo = new ProcessStartInfo
            {
                FileName = "cmd.exe",
                Arguments = $"/c {command}",
                WorkingDirectory = workingDirectory ?? string.Empty,
                UseShellExecute = false,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                CreateNoWindow = !showWindow,
                StandardOutputEncoding = Encoding.UTF8,
                StandardErrorEncoding = Encoding.UTF8
            };

            using (var process = new Process())
            {
                process.StartInfo = startInfo;

                Console.WriteLine($"[CmdUtils] 启动进程...");
                process.Start();

                string output = process.StandardOutput.ReadToEnd();
                string error = process.StandardError.ReadToEnd();

                process.WaitForExit();

                Console.WriteLine($"[CmdUtils] 进程退出代码: {process.ExitCode}");

                if (!string.IsNullOrEmpty(output))
                {
                    Console.WriteLine($"[CMD-OUTPUT] {output}");
                }

                if (!string.IsNullOrEmpty(error))
                {
                    Console.WriteLine($"[CMD-ERROR] {error}");
                }

                return output + (string.IsNullOrEmpty(error) ? "" : $"\n[ERROR]\n{error}");
            }
        }
    }
}